import json
import uvicorn
from threading import Thread
from fastapi import FastAPI
from fastapi.requests import Request
from fastapi.responses import JSONResponse
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.middleware.cors import CORSMiddleware

from src.utils.tool import Tool
from src.logger import Logger
from src.process import ExeControl
from src.bot.robot import Robot
from src.conf.conf_manager import ConfManager


class Server:
    def __init__(self, conf: ConfManager, logger: Logger, dls: ExeControl, bot: Robot):
        self.__logger = logger
        self.__conf = conf
        self.__dls = dls
        self.__bot = bot
        # 应用相关(gzip与cors)
        self.__app = FastAPI()
        self.__app.add_middleware(GZipMiddleware)
        # 允许跨域后, 禁止服务端使用cookie
        self.__app.add_middleware(
            CORSMiddleware,
            allow_origins=["*"],
            allow_methods=["*"],
            allow_headers=["*"],
        )
        self.__bind_event()

    def __bind_event(self):
        """绑定接收请求函数"""

        @self.__app.post('/execute')
        # 执行内置命令
        async def func(request: Request):
            try:
                params = json.loads(await request.body())
                if not self.identity_verify(params):
                    return JSONResponse({"code": 403, "msg": "身份未验证!"}, status_code=403)
                # 添加至命令队列中
                self.__logger.add_cmd(params.get("cmd"))
                return JSONResponse({"code": 200, "msg": "提交命令成功!"})
            except Exception as e:
                return JSONResponse({"code": 500, "msg": f"数据格式不合法！{e}"}, status_code=500)

        @self.__app.get('/process_status')
        # 获取进程在线状态
        async def func():
            return JSONResponse({"code": 200, "online": self.__dls.exe_alive})

        @self.__app.get('/server_status')
        # 获取硬件使用状态
        async def func():
            res = {"code": 200}
            res.update(Tool.get_status(raw=True))
            return JSONResponse(res)

        @self.__app.get('/terminal_log')
        # 获取控制台输出
        async def func(request: Request):
            try:
                params = dict(request.query_params)
                # 身份验证
                if not self.identity_verify(params):
                    return JSONResponse({"code": 403, "msg": "身份未验证!"}, status_code=403)
                # 返回最新控制台输出
                log_id = int(params.get("log_id", 0))
                return JSONResponse({"code": 200, "log_list": self.__logger.latest_record_log(log_id)})
            except Exception as e:
                return JSONResponse({"code": 500, "msg": f"数据格式不合法！{e}"}, status_code=500)

        @self.__app.post('/terminal_log')
        # 插入控制台输出
        async def func(request: Request):
            try:
                params = json.loads(await request.body())
                # 身份验证
                if not self.identity_verify(params):
                    return JSONResponse({"code": 403, "msg": "身份未验证!"}, status_code=403)
                # 添加文本到logger中
                text: str = params.get("text", "")
                if text:
                    self.__logger.add_log(text)
                return JSONResponse({"code": 200, "msg": "成功添加输出!"})
            except Exception as e:
                return JSONResponse({"code": 500, "msg": f"数据格式不合法！{e}"}, status_code=500)

        @self.__app.get('/config')
        # 获取用户配置内容
        async def func(request: Request):
            try:
                params = dict(request.query_params)
                # 身份验证
                if not self.identity_verify(params):
                    return JSONResponse({"code": 403, "msg": "身份未验证!"}, status_code=403)
                # 返回用户配置
                conf_name = params.get("conf_name")
                return JSONResponse({"code": 200, "data": self.__conf.get_conf(conf_name)})
            except Exception as e:
                return JSONResponse({"code": 500, "msg": f"数据格式不合法！{e}"}, status_code=500)

        @self.__app.post('/config')
        # 修改用户配置内容
        async def func(request: Request):
            try:
                params = json.loads(await request.body())
                # 身份验证
                if not self.identity_verify(params):
                    return JSONResponse({"code": 403, "msg": "身份未验证!"}, status_code=403)
                # 修改用户配置
                self.__conf.update_conf(params.get("conf_dict"))
                return JSONResponse({"code": 200, "msg": "配置文件加载完成！"})
            except Exception as e:
                return JSONResponse({"code": 500, "msg": f"数据格式不合法！{e}"}, status_code=500)

    # 根据params验证身份
    def identity_verify(self, params: dict) -> bool:
        if params.get("token") == self.__conf.conf.server_token:
            return True
        else:
            return False

    def start(self):
        # 端口正确设置时才启动服务
        if not self.__conf.conf.server_port:
            return

        def run():
            # host为空字符串时，同时支持ipv4与ipv6
            uvicorn.run(app=self.__app, host="", port=self.__conf.conf.server_port,
                        log_level="error", use_colors=True)

        Thread(target=run, daemon=True).start()
        self.__logger.add_log(f"[DLS] API服务成功启用！地址: http://127.0.0.1:{self.__conf.conf.server_port}")
